package com.l.controller;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Properties;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.l.pay.app.PayCommonUtil;
import com.l.pay.app.UtilDate;
import com.l.pay.app.WxPayConfig;
import com.l.pay.app.XMLUtil4jdom;
@Controller
public class WxPayController {
	@Autowired
	/*private FrontService frontService;
	private static Logger logger = Logger.getLogger(WxPayUtil.class);*/
	 String noncestr=PayCommonUtil.CreateNoncestr();
    String timestamp=Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0,10))+"";
	
	//获取微信支付配置
	@RequestMapping("/getPayConfig")
	@ResponseBody
    public Map<Object, Object> getPayConfig(String url)
    {
		Map<Object, Object> map = new TreeMap<Object, Object>();
    	//获取AccessToken  
        String accessToken = getAccessToken();  
        //获取Ticket  
        String jsapi_ticket = getTicket(accessToken);
       
        String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;  
        //将字符串进行sha1加密  
        String signature =SHA1(str); 
        map.put("noncestr", noncestr);
        map.put("timestamp", timestamp);
        map.put("appId", WxPayConfig.appid);
        map.put("signature", signature);
        return map;
    }
	/**
	 * 统一下单
	 * 
	 * @param body
	 *            商品描述
	 * @param out_trade_no
	 *            商户订单号
	 * @param total_fee
	 *            标价金额
	 * @param IP
	 *            终端IP
	 * @param notify_url
	 *            回调地址
	 * @param openid
	 *            openid
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping("/wxpay")
	@ResponseBody
	public Map<Object, Object> unifiedOrder(HttpServletRequest request, double czmoney,
			String openid, int userid, String shopid, String shopname)
			throws Exception {
		String ordernum = UtilDate.getOrderNum();
		SortedMap<Object,Object> sArray = new TreeMap<Object,Object>();
		sArray.put("appid", WxPayConfig.appid);
		sArray.put("mch_id", WxPayConfig.mch_id);
		sArray.put("fee_type", "CNY");    
		sArray.put("device_info", WxPayConfig.device_info);
		sArray.put("body", "wxpay");
		sArray.put("nonce_str", noncestr);
		sArray.put("out_trade_no",ordernum);
		BigDecimal b = new BigDecimal(czmoney);
		BigDecimal r = b.multiply(new BigDecimal("100"));
		String s=r.toString();
		if(s.indexOf(".") > 0){
			  s = s.replaceAll("0+?$", "");//去掉后面无用的零
			  s = s.replaceAll("[.]$", "");//如小数点后面全是零则去掉小数点
			}
		sArray.put("total_fee", s);
		sArray.put("notify_url", WxPayConfig.notify_url);
		sArray.put("trade_type", "JSAPI");
		sArray.put("sign_type", "MD5");
		sArray.put("openid", openid);
		//设置签名
        String sign = PayCommonUtil.createSign("UTF-8",sArray);
        sArray.put("sign", sign);
      //封装请求参数结束
        String requestXML = PayCommonUtil.getRequestXml(sArray);  
       //调用统一下单接口
        String result = PayCommonUtil.httpsRequest(WxPayConfig.service, "POST", requestXML);
        Map<Object, Object> parameterMap2 = new TreeMap<Object, Object>();  
        try {
        /**统一下单接口返回正常的prepay_id，再按签名规范重新生成签名后，将数据传输。参与签名的字段名为appId，partnerId，prepayId，nonceStr，timeStamp，package。**/
           Map<String, String> parameterMap1 = XMLUtil4jdom.doXMLParse(result);
            
           parameterMap2.put("appId", WxPayConfig.appid);  
           String prepayid=parameterMap1.get("prepay_id");
           parameterMap2.put("package", "prepay_id="+prepayid); 
           parameterMap2.put("nonceStr", parameterMap1.get("nonce_str"));  
           parameterMap2.put("timeStamp", timestamp); 
           parameterMap2.put("signType", "MD5");
           String sign2 = PayCommonUtil.createSign("utf-8",parameterMap2);
           parameterMap2.put("prepayid",prepayid);  
           parameterMap2.put("paySign", sign2);  
       } catch (JDOMException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
		return parameterMap2;
	}

	/**
	 * 修改订单状态，获取微信回调结果
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping("/receive_wx_pay")
	public void getNotifyResult(HttpServletRequest request,HttpServletResponse response) {
		String inputLine;
		String notifyXml = "";
		String resXml = "";
		try {
			while ((inputLine = request.getReader().readLine()) != null) {
				notifyXml += inputLine;
			}
			request.getReader().close();
		} catch (Exception e) {
			//logger.debug("xml获取失败：" + e);
			e.printStackTrace();
		}
		System.out.println("接收到的xml：" + notifyXml);
		//logger.debug("收到微信异步回调：");
		//logger.debug(notifyXml);

		String appid = getXmlPara(notifyXml, "appid");
		String bank_type = getXmlPara(notifyXml, "bank_type");
		String cash_fee = getXmlPara(notifyXml, "cash_fee");
		String fee_type = getXmlPara(notifyXml, "fee_type");
		String is_subscribe = getXmlPara(notifyXml, "is_subscribe");
		String mch_id = getXmlPara(notifyXml, "mch_id");
		String nonce_str = getXmlPara(notifyXml, "nonce_str");
		String openid = getXmlPara(notifyXml, "openid");
		String out_trade_no = getXmlPara(notifyXml, "out_trade_no");
		String result_code = getXmlPara(notifyXml, "result_code");
		String return_code = getXmlPara(notifyXml, "return_code");
		String sign = getXmlPara(notifyXml, "sign");
		String time_end = getXmlPara(notifyXml, "time_end");
		String total_fee = getXmlPara(notifyXml, "total_fee");
		String trade_type = getXmlPara(notifyXml, "trade_type");
		String transaction_id = getXmlPara(notifyXml, "transaction_id");

		Map<Object, Object> parameterMap2 = new TreeMap<Object, Object>();
		parameterMap2.put("appid", appid);
		parameterMap2.put("device_info", "WEB");
		parameterMap2.put("bank_type", bank_type);
		parameterMap2.put("cash_fee", cash_fee);
		parameterMap2.put("fee_type", fee_type);
		parameterMap2.put("is_subscribe", is_subscribe);
		parameterMap2.put("mch_id", mch_id);
		parameterMap2.put("nonce_str", nonce_str);
		parameterMap2.put("openid", openid);
		parameterMap2.put("out_trade_no", out_trade_no);
		parameterMap2.put("result_code", result_code);
		parameterMap2.put("return_code", return_code);
		parameterMap2.put("time_end", time_end);
		parameterMap2.put("total_fee", total_fee);
		parameterMap2.put("trade_type", trade_type);
		parameterMap2.put("transaction_id", transaction_id);
		String sign2 = PayCommonUtil.createSign("utf-8", parameterMap2);

		System.out.println("本地签名是：" + sign2);
		/*logger.debug("本地签名是：" + localSign);
		logger.debug("微信支付签名是：" + sign);*/

		// 本地计算签名与微信返回签名不同||返回结果为不成功
		if (!sign.equals(sign2) || !"SUCCESS".equals(result_code)
				|| !"SUCCESS".equals(return_code)) {
			System.out.println("验证签名失败或返回错误结果码");
			//logger.error("验证签名失败或返回错误结果码");
			resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
					+ "<return_msg><![CDATA[FAIL]]></return_msg>" + "</xml> ";
			try {
				response.getWriter().write(resXml);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {
			System.out.println("支付成功");
			//logger.debug("公众号支付成功，out_trade_no(订单号)为：" + out_trade_no);
			//先判断状态是否为0
			//frontService.updateCzstatus(out_trade_no);
			resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
					+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
			try {
				response.getWriter().write(resXml);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 插入XML标签
	 * 
	 * @param sb
	 * @param Key
	 * @param value
	 * @return
	 */
	public static StringBuilder setXmlKV(StringBuilder sb, String Key,
			String value) {
		sb.append("<");
		sb.append(Key);
		sb.append(">");

		sb.append(value);

		sb.append("</");
		sb.append(Key);
		sb.append(">");

		return sb;
	}

	/**
	 * 解析XML 获得名称为para的参数值
	 * 
	 * @param xml
	 * @param para
	 * @return
	 */
	public static String getXmlPara(String xml, String para) {
		int start = xml.indexOf("<" + para + ">");
		int end = xml.indexOf("</" + para + ">");

		if (start < 0 && end < 0) {
			return null;
		}
		return xml.substring(start + ("<" + para + ">").length(), end)
				.replace("<![CDATA[", "").replace("]]>", "");
	}

	/**
	 * 获取ip地址
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		InetAddress addr = null;
		try {
			addr = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			return request.getRemoteAddr();
		}
		byte[] ipAddr = addr.getAddress();
		String ipAddrStr = "";
		for (int i = 0; i < ipAddr.length; i++) {
			if (i > 0) {
				ipAddrStr += ".";
			}
			ipAddrStr += ipAddr[i] & 0xFF;
		}
		return ipAddrStr;
	}
	public static String getAccessToken() {
	    String access_token = "";
	    String grant_type = "client_credential";//获取access_token填写client_credential 
	    String AppId = "";
		String secret = "";
		Properties prop = new Properties();
		InputStream input = Thread.currentThread().getContextClassLoader()
				.getResourceAsStream("appconfig.properties");
		try {
			prop.load(input);
			AppId = prop.getProperty("appid");
			secret = prop.getProperty("appsecret");
			prop.clear();
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	    //这个url链接地址和参数皆不能变
	    String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+grant_type+"&appid="+AppId+"&secret="+secret;
	     
	    try {
	        URL urlGet = new URL(url);
	        HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
	        http.setRequestMethod("GET"); // 必须是get方式请求
	        http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
	        http.setDoOutput(true);
	        http.setDoInput(true);
	        System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
	        System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
	        http.connect();
	        InputStream is = http.getInputStream();
	        int size = is.available();
	        byte[] jsonBytes = new byte[size];
	        is.read(jsonBytes);
	        String message = new String(jsonBytes, "UTF-8");
	        JSONObject demoJson = JSONObject.fromObject(message);
	        System.out.println("JSON字符串："+demoJson);
	        access_token = demoJson.getString("access_token");
	        is.close();
	    } catch (Exception e) {
	            e.printStackTrace();
	    }
	    return access_token;
	}
	public static String getTicket(String access_token) {
	    String ticket = null;
	    String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//这个url链接和参数不能变
	    try {
	        URL urlGet = new URL(url);
	        HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
	        http.setRequestMethod("GET"); // 必须是get方式请求
	        http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
	        http.setDoOutput(true);
	        http.setDoInput(true);
	        System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
	        System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
	        http.connect();
	        InputStream is = http.getInputStream();
	        int size = is.available();
	        byte[] jsonBytes = new byte[size];
	        is.read(jsonBytes);
	        String message = new String(jsonBytes, "UTF-8");
	        JSONObject demoJson = JSONObject.fromObject(message);
	        System.out.println("JSON字符串："+demoJson);
	        ticket = demoJson.getString("ticket");
	        is.close();
	    } catch (Exception e) {
	            e.printStackTrace();
	    }
	    return ticket;
	}
	public static String SHA1(String decript) {
	    try {
	        MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
	        digest.update(decript.getBytes());
	        byte messageDigest[] = digest.digest();
	        // Create Hex String
	        StringBuffer hexString = new StringBuffer();
	        // 字节数组转换为 十六进制 数
	            for (int i = 0; i < messageDigest.length; i++) {
	                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
	                if (shaHex.length() < 2) {
	                    hexString.append(0);
	                }
	                hexString.append(shaHex);
	            }
	            return hexString.toString();
	 
	        } catch (NoSuchAlgorithmException e) {
	            e.printStackTrace();
	        }
	        return "";
	}
}
